package com.test.filter;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.test.entity.Const;
import com.test.utils.JwtUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component

public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Resource
    JwtUtils utils;
    /**
     * 自定义过滤器，用于处理除认证请求外的其他请求
     * @param request 请求对象
     * @param response 响应对象
     * @param filterChain 过滤器链对象
     * @throws ServletException 如果过滤过程中发生Servlet异常
     * @throws IOException 如果过滤过程中发生IO异常
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 判断请求是否以"/api/auth/"开头，如果不是，则进行JWT令牌验证
        if (!request.getRequestURI().startsWith("/api/auth/")) {
            // 检查JWT令牌
            String authorization = request.getHeader("Authorization");
            DecodedJWT resolve = utils.resolve(authorization);
            if(resolve != null){
                // 将JWT令牌解析为用户信息，并创建认证令牌
                UserDetails user = utils.toUser(resolve);
                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                // 然后直接把配置好的Authentication塞给SecurityContext表示已经完成验证
                SecurityContextHolder.getContext().setAuthentication(authentication);
                // 在请求属性中设置用户ID，以便后续使用
                request.setAttribute(Const.VERIFY_USER_ID, resolve.getClaim("id").asInt());
                System.out.println(request.getAttribute(Const.VERIFY_USER_ID));
            }
        }
        // 传给下级过滤器
        filterChain.doFilter(request,response);
    }
}
